home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / infofile.i < prev    next >
Text File  |  1997-10-26  |  30KB  |  998 lines

  1. IMPLEMENTATION MODULE Infofiles;
  2. (*$Z+*)
  3.  
  4. (* Beschreibung des Datenformates: 
  5.  * Die Infofiles im Speicher werden als verkettete Liste 
  6.  * von infEntrys dargestellt. Dabei wird fr einen Eintrag 
  7.  * nur so viel Speicher alloziert, wie unbedingt notwendig.
  8.  * Auf Platte werden die Files als Array [0..#Infofiles] 
  9.  * von infEntrys abgespeichert, wobei diese natrlich den
  10.  * vollen Platz belegen.
  11.  *)
  12.  
  13. FROM SYSTEM  IMPORT ADDRESS, ADR, TSIZE, CALLSYS, CADR;
  14.  
  15. (* MM2-Module *)
  16. FROM Storage IMPORT ALLOCATE, DEALLOCATE;
  17. IMPORT Lists, Block, GrafBase;
  18.  
  19. (* CAT-Module *)
  20. FROM MTPaths IMPORT DataPath;
  21. FROM Void    IMPORT v;
  22. IMPORT CatFiles, MTE, dataSys, CatGlobal, ConvertDate, QuickSort, GroupSelect, 
  23.        CatTypes, Protokoll;
  24.  
  25. (* Magic-Module *)
  26.  
  27. IMPORT MagicConvert, MagicStrings, MagicDOS, 
  28.        MagicAES, MagicVDI, mtAlerts, mtUtils, mtPopups, 
  29.        mtAppl, mtTextfiles;
  30.  
  31. CONST   CreateDefault = FALSE;
  32.  
  33. CONST   infoInfFile     = 'info.inf';
  34.  
  35.         (* Magics fr Header *)
  36.         infCatMagic     = 43415449H;  (* "CATI"                    *)
  37.         oldInfVersion   = 1;          (* alte Versionsnummer der Infofile.i *)
  38.         oldInfVersionMagic = 0140H;   (* altes Versionsmagic       *)
  39.  
  40.         infVersion      = 2;          (* Versionsnummer der Infofile.i *)
  41.         infVersionMagic = 0100H;      (* Versionsmagic             *)
  42.  
  43.         maxInf          = 1024;
  44.  
  45. TYPE 
  46.         oldInfEntry = RECORD
  47.                   crc   : CARDINAL;
  48.                   new   : BOOLEAN;
  49.                   avail : BOOLEAN;
  50.                   isMaus: BOOLEAN;
  51.                   ordered: BOOLEAN;
  52.                   orderIntervall: INTEGER; (* -1: Einmalig, 0: Immer, 1: t„glich *)
  53.                   lastOrdered: LONGCARD; (* Datum in Tagen seit dem 1.1.1900 *)
  54.                   selected: BOOLEAN;
  55.                   hasCrc: tCrcState;
  56.                   res   : CARDINAL;
  57.                   mausShort : ARRAY [0..9] OF CHAR;
  58.                   mausName  : ARRAY [0..35] OF CHAR;
  59.                   filename  : ARRAY [0..255] OF CHAR;
  60.                 END;
  61.      
  62.         oldInfEntryPtr = POINTER TO oldInfEntry;
  63.      
  64.         oldInfArrayType = ARRAY [0..maxInf-1] OF oldInfEntry;
  65.      
  66.         oldInfArrayPtr = POINTER TO oldInfArrayType;
  67.      
  68.      infArrayType = ARRAY [0..maxInf-1] OF infEntry;
  69.      
  70.      infArrayPtr = POINTER TO infArrayType;
  71.  
  72. VAR infLoaded: BOOLEAN;
  73.     
  74. PROCEDURE InfoLoaded(): BOOLEAN;
  75. BEGIN
  76.   RETURN infLoaded;
  77. END InfoLoaded;
  78.  
  79. PROCEDURE DeleteSimpleList (VAR l: Lists.List; killCarrier: BOOLEAN);
  80.  
  81. VAR   entry: ADDRESS;
  82.  
  83. BEGIN
  84.   Lists.ResetList (l);
  85.   entry := Lists.PrevEntry (l);
  86.   WHILE entry # NIL DO
  87.     Lists.RemoveEntry (l, v.bool);
  88.     DEALLOCATE (entry, 0L);
  89.     entry := Lists.CurrentEntry (l);
  90.   END;
  91.   IF killCarrier THEN Lists.DeleteList (l, v.bool) END;
  92. END DeleteSimpleList;
  93.  
  94. PROCEDURE SortList (VAR l : Lists.List);                        (* exported *)
  95. (* sortiert die Gruppenliste *)
  96.   VAR count : CARDINAL;
  97.       sort  : POINTER TO ARRAY [0..$FFFF] OF ADDRESS;
  98.       i     : CARDINAL;
  99.       adr   : ADDRESS;
  100.  
  101.   PROCEDURE grComp (a1, a2 : ADDRESS) : BOOLEAN;
  102.     VAR b1, b2 : POINTER TO infEntryPtr;
  103.         p1, p2 : infEntryPtr;
  104.         str1, str2 : ARRAY [0..9] OF CHAR;
  105.   BEGIN
  106.     b1 := a1; b2 := a2;
  107.     p1 := infEntryPtr (b1^);
  108.     p2 := infEntryPtr (b2^);
  109.     MagicStrings.Assign (p1^.mausShort, str1);
  110.     MagicStrings.Assign (p2^.mausShort, str2);
  111.     MagicStrings.CAPS (str1);
  112.     MagicStrings.CAPS (str2);
  113.     IF p1^.isMaus = p2^.isMaus
  114.     THEN
  115.       RETURN MagicStrings.Compare (str1, str2) = MagicStrings.less;
  116.     ELSE
  117.       RETURN p1^.isMaus
  118.     END;
  119.   END grComp;
  120.  
  121. BEGIN
  122.   count := Lists.NoOfEntries (l);
  123.   IF count = 0 THEN RETURN END;
  124.   ALLOCATE (sort, LONG(count+1) * TSIZE (ADDRESS));
  125.   IF sort = NIL THEN RETURN END;
  126.   Lists.ResetList (l);
  127.   FOR i := 0 TO count-1 DO
  128.     sort^[i] := Lists.NextEntry (l);
  129.   END;
  130.   v.bool := QuickSort.sortIt (0, count-1, sort^, grComp, TSIZE (ADDRESS), QuickSort.noBreak);
  131.   (* Liste wieder zurckbernehmen *)
  132.   Lists.ResetList (l);
  133.   adr := Lists.PrevEntry (l);
  134.   WHILE adr # NIL DO
  135.     Lists.RemoveEntry (l, v.bool);
  136.     IF v.bool THEN HALT END;
  137.     adr := Lists.CurrentEntry (l);
  138.   END;
  139.   (*
  140.   FOR i := 0 TO count-1 DO
  141.     adr := Lists.NextEntry (l);
  142.     Lists.RemoveEntry (l, v.bool);
  143.     IF v.bool THEN HALT END;
  144.   END;
  145.   *)
  146.   Lists.ResetList (l);
  147.   FOR i := 0 TO count - 1 DO 
  148.     IF sort^[i] # NIL
  149.     THEN
  150.       Lists.AppendEntry (l, sort^[i], v.bool);
  151.       IF v.bool THEN HALT END;
  152.     END;
  153.   END;
  154.   DEALLOCATE (sort, 0);
  155. END SortList;
  156.  
  157. PROCEDURE IsNeededInfo (REF str: ARRAY OF CHAR): BOOLEAN;
  158.   VAR i: CARDINAL;
  159. BEGIN
  160.   (* Kompliziertere Abfrage, damit man das nicht so leicht 
  161.    * rauspatchen kann!
  162.    * Einfacher w„re folgendes: 
  163.    * IF MagicStrings.Equal (mausShort, "ITG")
  164.    * OR MagicStrings.Equal (mausShort, "ITI")
  165.    * OR MagicStrings.Equal (mausShort, "ITK")
  166.    *)
  167.   IF (INTEGER(ORD (str[0])) - INTEGER(ORD('I')) = 0)
  168.    & (INTEGER(ORD (str[1])) - INTEGER(ORD('T')) = 0)
  169.   THEN
  170.     FOR i := 0 TO 4  BY 2 DO
  171.       (* ITG, ITI und ITK werden geprft. 
  172.        * G + 0 = G
  173.        * G + 2 = I
  174.        * G + 4 = K
  175.        *)
  176.       IF ORD(str[2]) = ORD('G') + i
  177.       THEN
  178.         RETURN TRUE;
  179.       END;
  180.     END;
  181.   END;
  182.   RETURN FALSE;
  183. END IsNeededInfo;
  184.  
  185. PROCEDURE ConvertInfoV1toV2 (REF old: oldInfEntry; VAR new : infEntry);
  186. BEGIN
  187.   WITH new DO
  188.     crc := old.crc;
  189.     new := old.new;
  190.     avail := old.avail;
  191.     isMaus := old.isMaus;
  192.     ordered := old.ordered;
  193.     orderIntervall := old.orderIntervall;
  194.     lastOrdered := old.lastOrdered;
  195.     selected := old.selected;
  196.     hasCrc := old.hasCrc;
  197.     res    := old.res;
  198.     MagicStrings.Assign (old.mausShort, mausShort);
  199.     MagicStrings.Assign (old.mausName, mausName);
  200.     MagicStrings.Assign (old.filename, filename);
  201.   END;
  202. END ConvertInfoV1toV2;
  203.  
  204. (*$H+*)
  205. PROCEDURE LoadInfoInf(dbChanged, clearNew : BOOLEAN);
  206.  VAR    handle  : INTEGER;
  207.         bSize   : CARDINAL;
  208.         size    : LONGCARD;
  209.         count   : CARDINAL;
  210.         entry   : infEntryPtr;
  211.         infArray: infArrayPtr;
  212.         oldInfArray: oldInfArrayPtr;
  213.         i       : CARDINAL;
  214.         l       : CARDINAL;
  215.         dbHdr   : dataSys.FileHeaderType;
  216.         isOldInf: BOOLEAN;
  217.  
  218. (*$Z-*)
  219.   PROCEDURE clearNewProc (entry, info : ADDRESS): BOOLEAN;
  220.     VAR e : infEntryPtr;
  221.   BEGIN
  222.     e := infEntryPtr (entry);
  223.     e^.new := FALSE;
  224.     RETURN FALSE;
  225.   END clearNewProc;
  226. (*$Z+*)
  227.  
  228. BEGIN
  229.   handle := -1;
  230.   handle := CatFiles.OpenFile(DataPath, infoInfFile, CatFiles.readFile);
  231.   IF handle > 0 THEN
  232.     (* Jetzt erst mal Header einlesen *)
  233.     CatFiles.Seek (0, handle, CatFiles.start);
  234.     CatFiles.ReadMuch (dataSys.dbHeaderLength, handle, ADR(dbHdr));
  235.     IF CatFiles.FileError # CatFiles.NoError
  236.     THEN
  237.       CatFiles.ErrorAlert (CatFiles.FileError);
  238.       CatFiles.CloseFile (handle);
  239.       RETURN
  240.     END;
  241.     (* Jetzt berprfen des Headers *)
  242.     IF (dbHdr.CatMagic # infCatMagic)
  243.     OR (dbHdr.Version  # infVersion)
  244.     OR (dbHdr.VersionMagic # infVersionMagic)
  245.     THEN
  246.       IF (dbHdr.CatMagic = infCatMagic)
  247.        & (dbHdr.Version  = oldInfVersion)
  248.        & (dbHdr.VersionMagic  = oldInfVersionMagic)
  249.       THEN
  250.         isOldInf := TRUE;
  251.       ELSE
  252.         MTE.info (MTE.oldVersionAlt);
  253.         CatFiles.CloseFile (handle);
  254.         RETURN
  255.       END;
  256.     ELSE
  257.       isOldInf := FALSE;
  258.     END;
  259.     (* Gr”že feststellen *)
  260.     CatFiles.Seek (0, handle, CatFiles.end);
  261.     size := CatFiles.FilePos (handle);
  262.     CatFiles.Seek (0, handle, CatFiles.start);
  263.     IF isOldInf
  264.     THEN
  265.       count := SHORT((size-dataSys.dbHeaderLength) DIV TSIZE (oldInfEntry));
  266.       IF count > maxInf THEN count := maxInf END;
  267.       ALLOCATE (oldInfArray, size - dataSys.dbHeaderLength);
  268.       IF oldInfArray = NIL THEN 
  269.         CatFiles.CloseFile (handle);
  270.         MTE.noMemAlert();
  271.         RETURN 
  272.       END;
  273.       (* Neues Array allozieren *)
  274.       ALLOCATE (infArray, LONG(count) * TSIZE (infEntry));
  275.       IF infArray = NIL THEN 
  276.         DEALLOCATE (oldInfArray, 0);
  277.         CatFiles.CloseFile (handle);
  278.         MTE.noMemAlert();
  279.         RETURN 
  280.       END;
  281.       Block.Clear (infArray, LONG (count) * TSIZE (infEntry));
  282.  
  283.       (* Jetzt Datenblock einlesen *)
  284.       CatFiles.Seek (TSIZE (dataSys.FileHeaderType), handle, CatFiles.start);
  285.       CatFiles.ReadMuch (size - dataSys.dbHeaderLength, handle, oldInfArray);
  286.       IF CatFiles.FileError # CatFiles.NoError
  287.       THEN
  288.         DEALLOCATE (infArray, 0);
  289.         DEALLOCATE (oldInfArray, 0);
  290.         CatFiles.ErrorAlert (CatFiles.FileError);
  291.         CatFiles.CloseFile (handle);
  292.         RETURN
  293.       END;
  294.       (* Jetzt Daten umkopieren *)
  295.       FOR i := 0 TO count - 1 DO
  296.         ConvertInfoV1toV2 (oldInfArray^[i], infArray^[i]);
  297.       END;
  298.       (* Und altes Array freigeben *)
  299.       DEALLOCATE (oldInfArray, 0);
  300.     ELSE
  301.       count := SHORT((size-dataSys.dbHeaderLength) DIV TSIZE (infEntry));
  302.       IF count > maxInf THEN count := maxInf END;
  303.       ALLOCATE (infArray, size - dataSys.dbHeaderLength);
  304.       IF infArray = NIL THEN 
  305.         CatFiles.CloseFile (handle);
  306.         MTE.noMemAlert();
  307.         RETURN 
  308.       END;
  309.       (* Jetzt Datenblock einlesen *)
  310.       CatFiles.Seek (TSIZE (dataSys.FileHeaderType), handle, CatFiles.start);
  311.       CatFiles.ReadMuch (size - dataSys.dbHeaderLength, handle, infArray);
  312.       IF CatFiles.FileError # CatFiles.NoError
  313.       THEN
  314.         CatFiles.ErrorAlert (CatFiles.FileError);
  315.         CatFiles.CloseFile (handle);
  316.         DEALLOCATE (infArray, 0);
  317.         RETURN
  318.       END;
  319.     END;
  320.     CatFiles.CloseFile (handle);
  321.     (* clearNew beachten *)
  322.     IF clearNew
  323.     THEN
  324.       FOR i := 0 TO count-1 DO
  325.         infArray^[i].new := FALSE;
  326.       END;
  327.     END;
  328.     (* Alte Liste l”schen, falls nicht leer *)
  329.     DeleteSimpleList (infList, FALSE);
  330.     (* Jetzt umwandeln in Liste *)
  331.     FOR i := 0 TO count-1 DO
  332.       l := (*SYSTEM.*)LENGTH (infArray^[i].filename);
  333.       bSize := TSIZE (infEntry) - 256 + l + 2;
  334.       ALLOCATE (entry, bSize);
  335.       IF entry = NIL
  336.       THEN
  337.         DEALLOCATE (infArray, 0);
  338.         MTE.noMemAlert();
  339.         RETURN 
  340.       END;
  341.       (* Anforderungsintervall fr ITK, ITI und ITG auf 'Immer' setzen,
  342.        * da nicht mehr „nderbar
  343.        *)
  344.       WITH infArray^[i] DO
  345.         IF IsNeededInfo (mausShort)
  346.         THEN
  347.           ordered := TRUE;
  348.           orderIntervall := 0;
  349.         END;
  350.       END;
  351.       Block.Copy (ADR(infArray^[i]), bSize, entry);
  352.       entry^.selected := FALSE;
  353.       entry^.res      := 0;
  354.       (*
  355.       WITH infArray^[i] DO
  356.         entry^.crc := crc;
  357.         entry^.new := new;
  358.         entry^.avail := avail;
  359.         entry^.isMaus := isMaus;
  360.         entry^.ordered := ordered;
  361.         entry^.orderIntervall := orderIntervall;
  362.         entry^.lastOrdered := lastOrdered;
  363.         MagicStrings.Assign (mausShort, entry^.mausShort);
  364.         MagicStrings.Assign (mausName, entry^.mausName);
  365.         MagicStrings.Assign (filename, entry^.filename);
  366.       END;
  367.       *)
  368.       Lists.AppendEntry (infList, entry, v.bool);
  369.       IF v.bool
  370.       THEN
  371.         DEALLOCATE (infArray, 0);
  372.         DEALLOCATE (entry, 0);
  373.         MTE.noMemAlert (); 
  374.         RETURN 
  375.       END;
  376.     END; (* FOR *)
  377.     infLoaded := TRUE;
  378.     DEALLOCATE (infArray, 0);
  379.     (* Jetzt sortieren *)
  380.     SortList (infList);
  381.     (* Und wenn es eine alte Liste war, dann direkt mal sichern *)
  382.     IF isOldInf 
  383.     THEN
  384.       SaveInfoInf();
  385.     END;
  386.   ELSE
  387.     IF dbChanged
  388.     THEN
  389.       (* Erstmal Benutzer informieren *)
  390.       MTE.info (MTE.noInfoInf);
  391.       (* Liste komplett leeren *)
  392.       DeleteSimpleList (infList, FALSE);
  393.     END;
  394.     (* Und jetzt Default-Eintr„ge anlegen. Diese sind:
  395.      * CAT CATLOG.TXT
  396.      * ERR PROTOKOL.TXT
  397.      * LOG Letztes Logfile der Maus
  398.      * ITI Technische Infofileliste
  399.      * ITG Technische Gruppenliste
  400.      * ITK Technische Kommandoliste
  401.      *)
  402.     v.bool := AddEntry (FALSE, FALSE, FALSE, FALSE, 0, 0, 
  403.                         0, 'CAT', 'CAT Einfgeprotokoll', '$Dcatlog.TXT', FALSE, cNoCrc);
  404.     v.bool := AddEntry (FALSE, FALSE, FALSE, FALSE, 0, 0, 
  405.                         0, 'ERR', 'CAT Errorfile', '$Dprotokol.TXT', FALSE, cNoCrc);
  406.     v.bool := AddEntry (FALSE, FALSE, FALSE, FALSE, 0, 0, 
  407.                         0, 'LOG', 'Letztes Logfile', '$DLOG.TXT', FALSE, cNoCrc);
  408.     v.bool := AddEntry (TRUE, TRUE, FALSE, FALSE, 0, 0, 
  409.                         0, 'ITI', 'Maschinenlesbare Infoliste', 'ITI.TXT', TRUE, cWithCrc);
  410.     v.bool := AddEntry (TRUE, TRUE, FALSE, FALSE, 0, 0, 
  411.                         0, 'ITG', 'Maschinenlesbare Gruppenliste', 'ITG.TXT', TRUE, cWithCrc);
  412.     v.bool := AddEntry (TRUE, TRUE, FALSE, FALSE, 0, 0, 
  413.                         0, 'ITK', 'Maschinenlesbare Kommandoliste', 'ITK.TXT', TRUE, cWithCrc);
  414.     (* Jetzt sortieren *)
  415.     SortList (infList);
  416.     IF clearNew
  417.     THEN
  418.       Lists.ResetList (infList);
  419.       Lists.ScanEntries (infList, Lists.forward, 
  420.                          clearNewProc, NIL, v.bool);
  421.     END;
  422.   END;
  423. END LoadInfoInf;
  424.  
  425. PROCEDURE SaveInfoInf();
  426.   VAR infArray  : infArrayPtr;
  427.  
  428.   (*$Z-*)
  429.   PROCEDURE copyEntry (e, i : ADDRESS): BOOLEAN;
  430.     VAR entry : infEntryPtr;
  431.         ix    : POINTER TO CARDINAL;
  432.         l, bSize : CARDINAL;
  433.   BEGIN
  434.     ix := i;
  435.     entry := infEntryPtr (e);
  436.     (*$? NOT CreateDefault: 
  437.     l := (*SYSTEM.*)LENGTH (entry^.filename);
  438.     bSize := TSIZE (infEntry) - 256 + l;
  439.     Block.Copy (entry, bSize, ADR(infArray^[ix^]));
  440.     *)
  441.     (*$? CreateDefault:
  442.     WITH infArray^[ix^] DO
  443.       crc    := entry^.crc;
  444.       new    := FALSE;
  445.       avail  := FALSE;
  446.       isMaus := entry^.isMaus;
  447.       ordered := (MagicStrings.Equal (entry^.mausShort, 'ITG') OR;
  448.                   MagicStrings.Equal (entry^.mausShort, 'ITI'));
  449.       orderIntervall := 0;
  450.       lastOrdered    := 0;
  451.       selected       := FALSE;
  452.       hasCrc         := cNA;
  453.       res            := 0;
  454.       MagicStrings.Assign (entry^.mausShort, mausShort);
  455.       MagicStrings.Assign (entry^.mausName, mausName);
  456.       MagicStrings.Assign (entry^.filename, filename);
  457.     END;
  458.     *)
  459.     INC (ix^);
  460.     RETURN FALSE;
  461.   END copyEntry;
  462.   (*$Z+*)
  463.   
  464.   VAR i          : CARDINAL;
  465.       handle     : INTEGER;
  466.       count      : CARDINAL;
  467.       entry      : infEntryPtr;
  468.       dbHdr      : dataSys.FileHeaderType;
  469. BEGIN
  470.   count := Lists.NoOfEntries (infList);
  471.   ALLOCATE (infArray, LONG(count) * TSIZE (infEntry));
  472.   IF infArray = NIL 
  473.   THEN
  474.     MTE.noMemAlert();
  475.     RETURN  
  476.   END;
  477.   Block.Clear (infArray, LONG(count) * TSIZE (infEntry));
  478.   Lists.ResetList (infList);
  479.   i := 0;
  480.   Lists.ScanEntries (infList, Lists.forward, copyEntry, ADR(i), v.bool);
  481.   (* Nun Datei erzeugen *)
  482.   (*$? CreateDefault:
  483.   handle := CatFiles.CreateFile (DataPath, "INFO.NEW");
  484.   *)
  485.   (*$? NOT CreateDefault:
  486.   handle := CatFiles.CreateFile (DataPath, infoInfFile);
  487.   *)
  488.   IF handle < 0 THEN 
  489.     CatFiles.ErrorAlert (handle); 
  490.     DEALLOCATE (infArray, 0);
  491.   END;
  492.   dbHdr.CatMagic := infCatMagic;
  493.   dbHdr.Version  := infVersion;
  494.   dbHdr.VersionMagic := infVersionMagic;
  495.   CatFiles.WriteMuch (dataSys.dbHeaderLength, handle, ADR(dbHdr));
  496.   IF CatFiles.FileError # CatFiles.NoError
  497.   THEN
  498.     CatFiles.ErrorAlert (CatFiles.FileError);
  499.     DEALLOCATE (infArray, 0);
  500.     CatFiles.CloseFile (handle);
  501.     RETURN
  502.   END;
  503.   CatFiles.WriteMuch (LONG(count) * TSIZE (infEntry), handle, infArray);
  504.   IF CatFiles.FileError # CatFiles.NoError
  505.   THEN
  506.     CatFiles.ErrorAlert (CatFiles.FileError);
  507.   END;
  508.   DEALLOCATE (infArray, 0);
  509.   CatFiles.CloseFile (handle);
  510.   Protokoll.SendPathUpdate (DataPath);
  511. END SaveInfoInf;
  512.  
  513. PROCEDURE ParseFlags (entry: infEntryPtr; REF flags: ARRAY OF CHAR);
  514.   VAR i, l : INTEGER;
  515. BEGIN
  516.   l := LENGTH (flags);
  517.   i := 0;
  518.   entry^.hasCrc := cNa;
  519.   WHILE i < l DO
  520.     CASE flags [i] OF 
  521.       'C'  : CASE flags[i+1] OF
  522.                 '+' : entry^.hasCrc  := cWithCrc; |
  523.                 '-' : entry^.hasCrc  := cNoCrc; |
  524.              ELSE
  525.                entry^.hasCrc := cNa;
  526.              END; |
  527.     ELSE
  528.     END;
  529.     INC (i, 2);
  530.   END;
  531. END ParseFlags;
  532.  
  533. (*$Z-*)
  534. PROCEDURE searchName (e, i : ADDRESS) : BOOLEAN;
  535.   VAR entry : infEntryPtr;
  536.       strPtr: POINTER TO ARRAY [0..255] OF CHAR;
  537. BEGIN
  538.   entry := e;
  539.   strPtr := i;
  540.   IF MagicStrings.Equal (entry^.mausShort, strPtr^)
  541.   THEN
  542.     RETURN TRUE
  543.   END;
  544.   RETURN FALSE
  545. END searchName;
  546. (*$Z+*)
  547.  
  548. PROCEDURE CheckInfos();
  549. (* Formatbeschreibung: 
  550.  
  551. Ansonsten mach' ich hier gleich mal einen Vorschlag fr das Info-Info, gleich
  552. mal via an die aktuellen Sožen angepažtem Beispiel:
  553.  
  554. #ITI
  555. :#IIE
  556. ::Einfhrung in die MAUS
  557. :#IIB
  558. ::Bedienungsanleitung
  559. :#IIA
  560. ::Men-Kurzanleitung
  561. :#IIG
  562. ::Gruppen-Anleitung
  563. :#III
  564. ::Technische Informationen
  565. :#IIH
  566. ::Hardware der MAUS
  567. :#IIM
  568. ::MAUS-Beitrag
  569. :#IIL
  570. ::LogIn-Zeiten
  571. :#IIT
  572. ::MausTausch-Anleitung
  573. :#IIK
  574. ::Kommerzielles
  575. :#INA
  576. ::MausNet-Anleitung
  577. :#INK
  578. ::Kurze Boxen-Liste
  579. :#INL
  580. ::Lange Boxen-Liste
  581. :#ING
  582. ::Netzgruppen-Liste
  583. :#INP
  584. ::Netzplan
  585. :#IGT
  586. ::Boxtitel
  587. :#IGE
  588. ::Boxabspann
  589. :#IGS
  590. ::Spruch des Tages
  591. :#IGK
  592. ::Kurze Gruppenliste
  593. :#IGL
  594. ::Lange Gruppenliste
  595. :#ISG                                 | erscheint nur,
  596. ::SysOp-Netzgruppenliste              | wenn User
  597. :#ISB                                 | berechtigt
  598. ::SysOp-Boxenliste                    | zum Abruf
  599. :#ITG
  600. ::Maschinenlesbare Gruppenliste
  601. :#ITI
  602. ::Maschinenlesbare Infoliste
  603.  
  604. Geht das so? Wenn ja, bau' ich das gleich ein ...
  605.  
  606. MfG Kai
  607. *)
  608.   VAR idScrap,
  609.       textScrap,
  610.       flagScrap,
  611.       infoScrap : ARRAY [0..255] OF CHAR;
  612.       name      : ARRAY [0..39] OF CHAR;
  613.       type      : CHAR;
  614.       tf        : mtTextfiles.TEXTFILE;
  615.       found     : BOOLEAN;
  616.       dummy     : infEntry;
  617.       entry     : infEntryPtr;
  618.       infoSet   : BOOLEAN;
  619.  
  620. BEGIN
  621.   MagicStrings.Assign (DataPath, idScrap);
  622.   MagicStrings.Append ('ITI.TXT', idScrap);
  623.   MagicStrings.Assign ('', infoScrap);
  624.   MagicStrings.Assign ('', flagScrap);
  625.   IF mtTextfiles.OpenTextfile (idScrap, mtTextfiles.READ, 8192, tf)
  626.   THEN
  627.     infoSet := FALSE;
  628.     (* Absolut trivial zu parsen *)
  629.     REPEAT
  630.       mtTextfiles.ReadChar(tf, type);
  631.       mtTextfiles.ReadLine(tf, idScrap);
  632.       mtTextfiles.ReadLn(tf);
  633.       CASE type OF
  634.         '#' : IF infoSet 
  635.               THEN
  636.                 (* Eintrag suchen und Infos sichern *)
  637.                 (* Beschreibung zu dem Infofile, also einsetzen *)
  638.                 Lists.ResetList (infList);
  639.                 Lists.ScanEntries (infList, Lists.forward, searchName, ADR(infoScrap), found);
  640.                 IF found 
  641.                 THEN
  642.                   entry := Lists.CurrentEntry (infList);
  643.                   ParseFlags (entry, flagScrap);
  644.                   IF textScrap[0] # ''
  645.                   THEN
  646.                     MagicStrings.Assign (textScrap, entry^.mausName);
  647.                   END;
  648.                   entry^.res := 1;
  649.                 ELSE
  650.                   (* Nicht vorhanden, also neues Infofile anlegen 
  651.                    * und anfordern 
  652.                    *)
  653.                   (* Filenamen zusammensetzen *)
  654.                   MagicStrings.Assign (infoScrap, name);
  655.                   MagicStrings.Append (CatTypes.textExt, name);
  656.                   (* Und zu Liste hinzufgen *)
  657.                   ParseFlags (ADR(dummy), flagScrap);
  658.                   (* Sichern ist nicht n”tig, wird am Ende eh gemacht *)
  659.                   v.bool := AddEntry (TRUE, FALSE, FALSE, FALSE, 0, -1,
  660.                                       0, infoScrap, textScrap, name, FALSE, dummy.hasCrc);
  661.                 END;
  662.                 infoSet := FALSE;
  663.                 MagicStrings.Assign ('', infoScrap);
  664.                 MagicStrings.Assign ('', flagScrap);
  665.               END;
  666.               IF idScrap[0] # ''
  667.               THEN 
  668.                 MagicStrings.Assign (idScrap, infoScrap); 
  669.                 infoSet := TRUE;
  670.               END;|
  671.       | ':' : MagicStrings.Assign (idScrap, textScrap);
  672.       | 'F' : MagicStrings.Assign (idScrap, flagScrap); 
  673.       | ELSE
  674.       END;
  675.     UNTIL mtTextfiles.EndofText(tf);
  676.     mtTextfiles.CloseTextfile (tf);
  677.     IF infoSet 
  678.     THEN
  679.       (* Eintrag suchen und Infos sichern *)
  680.       (* Beschreibung zu dem Infofile, also einsetzen *)
  681.       Lists.ResetList (infList);
  682.       Lists.ScanEntries (infList, Lists.forward, searchName, ADR(infoScrap), found);
  683.       IF found 
  684.       THEN
  685.         entry := Lists.CurrentEntry (infList);
  686.         ParseFlags (entry, flagScrap);
  687.         IF textScrap[0] # ''
  688.         THEN
  689.           MagicStrings.Assign (textScrap, entry^.mausName);
  690.         END;
  691.         entry^.res := 1;
  692.       ELSE
  693.         (* Nicht vorhanden, also neues Infofile anlegen 
  694.          * und anfordern 
  695.          *)
  696.         (* Filenamen zusammensetzen *)
  697.         MagicStrings.Assign (infoScrap, name);
  698.         MagicStrings.Append (CatTypes.textExt, name);
  699.         (* Und zu Liste hinzufgen *)
  700.         ParseFlags (ADR(dummy), flagScrap);
  701.         (* Sichern ist nicht n”tig, wird am Ende eh gemacht *)
  702.         v.bool := AddEntry (TRUE, FALSE, FALSE, FALSE, 0, -1,
  703.                             0, infoScrap, textScrap, name, FALSE, dummy.hasCrc);
  704.       END;
  705.     END;
  706.     (* Jetzt alle Maus-Infofiles l”schen, die nicht gerade kamen *)
  707.     Lists.ResetList (infList);
  708.     REPEAT
  709.       entry := Lists.NextEntry (infList);
  710.       IF (entry # NIL) & (entry^.isMaus) & (entry^.res = 0)
  711.       THEN
  712.         Lists.RemoveEntry (infList, v.bool);
  713.         DEALLOCATE (entry, 0);
  714.         Lists.ResetList (infList);
  715.         entry := Lists.NextEntry (infList);
  716.       END;
  717.     UNTIL entry = NIL;
  718.     (* Jetzt sortieren *)
  719.     SortList (infList);
  720.   END;
  721. END CheckInfos;
  722.  
  723. PROCEDURE SetInfoCrc (REF inf: ARRAY OF CHAR; VAR str : ARRAY OF CHAR);
  724.  
  725.   VAR today : LONGCARD; (* Tagesdatum in Tagen seit 1.1.1900 *)
  726.       isNew : BOOLEAN;
  727.  
  728.   (*$Z-*)
  729.   PROCEDURE setCrc (e, i : ADDRESS) : BOOLEAN;
  730.   (*$Z+*)
  731.     VAR crc : CARDINAL;
  732.         entry : infEntryPtr;
  733.   BEGIN
  734.     entry := infEntryPtr (e);
  735.     IF entry^.isMaus & MagicStrings.Equal (entry^.mausShort, inf)
  736.     THEN
  737.       crc := MagicConvert.StrToCard(str);
  738.       entry^.new := ~entry^.avail OR (crc # entry^.crc) OR (inf[0]='J');
  739.       isNew := entry^.new;
  740.       entry^.avail := TRUE;
  741.       entry^.crc := crc;
  742.       entry^.lastOrdered := today;
  743.       IF entry^.orderIntervall = -1
  744.       THEN
  745.         entry^.orderIntervall := 0;
  746.         entry^.ordered := FALSE;
  747.       END;
  748.       RETURN TRUE
  749.     END;
  750.     RETURN FALSE
  751.   END setCrc;
  752.  
  753. BEGIN
  754.   today := ConvertDate.DateInNum (MagicDOS.Tgetdate ());
  755.   isNew := FALSE;
  756.   Lists.ResetList (infList);
  757.   Lists.ScanEntries (infList, Lists.forward, setCrc, NIL, v.bool);
  758.   IF MagicStrings.Equal (inf, 'ITI') & isNew
  759.   THEN
  760.     (* Maschinenlesbare Infofileliste ist neu! 
  761.      * Also Abgleich zwischen Infoliste und internen Daten 
  762.      *)
  763.     CheckInfos ();
  764.   END;
  765.   (*
  766.   IF MagicStrings.Equal (inf, 'ITG') & isNew
  767.   THEN
  768.     (* Maschinenlesbare Gruppenliste abgleichen mit
  769.      * interner Gruppenliste
  770.      *)
  771.     v.bool := GroupSelect.ParseInfofile();
  772.   END; 
  773.   *)
  774. END SetInfoCrc;
  775.  
  776. PROCEDURE GetInfoCrc (VAR str : ARRAY OF CHAR; mode : infMode) : BOOLEAN;
  777. (* Liefert einen Infostring zurck. Bei Mode = IFIRST wird das erste Infofile
  778.  * zurckgeliefert, bei Mode = INEXT wird der n„chste zurckgeliefert.
  779.  * Wenn alle Infostrings geliefert wurden, dann wird FALSE zurckgegeben 
  780.  * (kann auch bei IFIRST passieren)
  781.  * Zwischen den Aufrufen sollte nicht anders auf die Liste
  782.  * zugegriffen werden, da ansonsten evtl. nicht alle angefordert
  783.  * werden oder einige doppelt angefordert werden.
  784.  *)
  785.  
  786.   VAR today : LONGCARD; (* Tagesdatum in Tagen seit 1.1.1900 *)
  787.       stunde: CARDINAL;
  788.       ti    : ConvertDate.Time;
  789.  
  790.   (*$Z-*)
  791.   PROCEDURE getCrc (e, i : ADDRESS) : BOOLEAN;
  792.   (*$Z+*)
  793.     VAR crc : CARDINAL;
  794.         entry : infEntryPtr;
  795.         numstr: ARRAY [0..9] OF CHAR;
  796.   BEGIN
  797.     entry := infEntryPtr (e);
  798.     IF entry^.isMaus & entry^.ordered 
  799.     THEN
  800.       IF entry^.avail 
  801.       THEN
  802.         IF (entry^.orderIntervall <= 0) 
  803.         OR ((entry^.lastOrdered + LONGCARD(LONG(entry^.orderIntervall)) = today)
  804.             & (stunde >= 3) (* Neues Infofile erst nach dem Nachtnetz anfordern*) )
  805.         OR (entry^.lastOrdered + LONGCARD(LONG(entry^.orderIntervall)) < today) (* aužer es ist schon noch etwas „lter *)
  806.         OR (entry^.lastOrdered > today)
  807.         THEN
  808.           MagicConvert.CardToStr(entry^.crc, 0, numstr);
  809.         ELSE
  810.           RETURN FALSE
  811.         END;
  812.       ELSE
  813.         MagicConvert.IntToStr (-1, 0, numstr);
  814.       END;
  815.       MagicStrings.Assign (entry^.mausShort, str);
  816.       IF (entry^.hasCrc = cWithCrc) OR 
  817.          ((entry^.hasCrc = cNa) & (str[0] # 'J'))
  818.       THEN
  819.         MagicStrings.Append (" ", str);
  820.         MagicStrings.Append (numstr, str);
  821.       END;
  822.       RETURN TRUE
  823.     END;
  824.     RETURN FALSE
  825.   END getCrc;
  826.  
  827. BEGIN
  828.   MagicStrings.Assign ("", str);
  829.   today := ConvertDate.DateInNum (MagicDOS.Tgetdate ());
  830.   ti := ConvertDate.UnpackTime(MagicDOS.Tgettime());
  831.   stunde := ti.hour;
  832.   IF mode = IFIRST
  833.   THEN
  834.     Lists.ResetList (infList);
  835.   END;
  836.   Lists.ScanEntries (infList, Lists.forward, getCrc, NIL, v.bool);
  837.   RETURN v.bool;
  838. END GetInfoCrc;
  839.  
  840. PROCEDURE AddEntry (isMausInf, order, avl, isNew : BOOLEAN; theCrc: CARDINAL; inter : INTEGER;
  841.                     lastOrder : LONGCARD; REF short, name, file : ARRAY OF CHAR;
  842.                     saveInf : BOOLEAN; withCrc: tCrcState): BOOLEAN;
  843.   VAR l, bSize  : CARDINAL;
  844.       entry     : infEntryPtr;
  845.  
  846. BEGIN
  847.   IF isMausInf THEN
  848.     (* Immer I??.TXT als Filename! *)
  849.     l := 15
  850.   ELSE
  851.     l := (*SYSTEM.*)LENGTH (file);
  852.   END;
  853.   bSize := TSIZE (infEntry) - 256 + l + 2;
  854.   ALLOCATE (entry, bSize);
  855.   IF entry = NIL
  856.   THEN
  857.     MTE.noMemAlert ();
  858.     RETURN FALSE
  859.   END;
  860.   Block.Clear (entry, bSize);
  861.   WITH entry^ DO
  862.     crc := theCrc;
  863.     avail := avl;
  864.     new   := isNew;
  865.     isMaus := isMausInf;
  866.     ordered := order;
  867.     orderIntervall := inter;
  868.     lastOrdered := lastOrder;
  869.     hasCrc := withCrc;
  870.     res := 1;
  871.     MagicStrings.Assign (short, mausShort);
  872.     MagicStrings.Assign (name, mausName);
  873.     IF ~isMausInf
  874.     THEN
  875.       MagicStrings.Assign (file, filename);
  876.     ELSE
  877.       MagicStrings.Assign (short, filename);
  878.       MagicStrings.Append (CatTypes.textExt, filename);
  879.     END;
  880.   END;
  881.   Lists.AppendEntry (infList, entry, v.bool);
  882.   IF v.bool
  883.   THEN
  884.     DEALLOCATE (entry, 0);
  885.     MTE.noMemAlert ();
  886.     RETURN FALSE
  887.   END;
  888.   IF saveInf THEN SaveInfoInf() END;
  889.   RETURN TRUE
  890. END AddEntry;
  891.  
  892. PROCEDURE buildName (info: infEntryPtr; VAR fname : ARRAY OF CHAR): BOOLEAN;
  893.   VAR filename : ARRAY [0..255] OF CHAR;
  894.       exists   : BOOLEAN;
  895. BEGIN
  896.   IF info^.isMaus
  897.   THEN
  898.     MagicStrings.Assign (DataPath, fname);
  899.     MagicStrings.Assign (info^.mausShort, filename);
  900.     MagicStrings.Append (CatTypes.textExt, filename);
  901.   ELSE
  902.     MagicStrings.Assign ("", fname);
  903.     MagicStrings.Assign (info^.filename, filename);
  904.     CatGlobal.ReplaceStr (filename, '$D', DataPath);
  905.   END;
  906.   MagicStrings.Append (filename, fname);
  907.   (* Jetzt Datei auf Existenz prfen und auf L„nge # 0 *)
  908.   IF CatFiles.FileSize (fname, exists) = 0 THEN 
  909.     (* Erstmal Listeintrag updaten, Infofile nicht da! *)
  910.     IF ~exists
  911.     THEN
  912.       info^.avail := FALSE;
  913.       info^.new := FALSE;
  914.       SaveInfoInf();
  915.     END;
  916.     RETURN FALSE
  917.   END;
  918.   RETURN TRUE
  919. END buildName;
  920.  
  921. PROCEDURE BuildName (info: ADDRESS; VAR fname : ARRAY OF CHAR): BOOLEAN;
  922. BEGIN
  923.   RETURN buildName (info, fname);
  924. END BuildName;
  925.  
  926. PROCEDURE GetInfoFilename (REF short: ARRAY OF CHAR; 
  927.                            VAR fname : ARRAY OF CHAR): BOOLEAN;
  928. (* Liefert zum Krzel des Infofiles den Filenamen. 
  929.  * FALSE: Infofile nicht vorhanden 
  930.  *)
  931.  
  932. VAR found : BOOLEAN;
  933.     info  : infEntryPtr;
  934.  
  935. BEGIN
  936.   (*$W-*)
  937.   Lists.ResetList (infList);
  938.   Lists.ScanEntries (infList, Lists.forward, searchName, ADR(short), found);
  939.   (*$W=*)
  940.   IF found
  941.   THEN
  942.     info := Lists.CurrentEntry (infList);
  943.     IF (info # NIL) & ~buildName (info, fname)
  944.     THEN
  945.       RETURN FALSE;
  946.     ELSIF (info=NIL)
  947.     THEN
  948.       RETURN FALSE;
  949.     END;
  950.   END;
  951.   RETURN found;
  952. END GetInfoFilename;
  953.  
  954. PROCEDURE IsInfoFile (REF short: ARRAY OF CHAR; onlyMaus: BOOLEAN): BOOLEAN;
  955. (* Liefert zurck, ob ein Krzel ein Infofile ist oder nicht 
  956.  *)
  957. VAR found : BOOLEAN;
  958.     info  : infEntryPtr;
  959. BEGIN
  960.   (*$W-*)
  961.   Lists.ResetList (infList);
  962.   Lists.ScanEntries (infList, Lists.forward, searchName, ADR(short), found);
  963.   (*$W=*)
  964.   IF found & onlyMaus
  965.   THEN
  966.     info := Lists.CurrentEntry (infList);
  967.     IF info # NIL
  968.     THEN
  969.       found := info^.isMaus
  970.     END;
  971.   END;
  972.   RETURN found
  973. END IsInfoFile;
  974.  
  975. PROCEDURE TestDirectParse (REF short: ARRAY OF CHAR);
  976. (* Wird vom Parser aufgerufen, wenn ein Infofile geschlossen wurde. Falls es 
  977.  * wichtige Informationen enth„lt (ITG), wird es dann direkt geparst
  978.  *)
  979. BEGIN
  980.   IF MagicStrings.Equal (short, 'ITG')
  981.   THEN
  982.     (* Maschinenlesbare Gruppenliste abgleichen mit
  983.      * interner Gruppenliste
  984.      *)
  985.     v.bool := GroupSelect.ParseInfofile();
  986.   ELSIF MagicStrings.Equal (short, 'REN')
  987.   THEN
  988.     (* Gruppen„nderungen parsen *)
  989.     GroupSelect.ParseRenamefile();
  990.   END;
  991. END TestDirectParse;
  992.  
  993.  
  994. (*$H=*)
  995. BEGIN
  996.   Lists.CreateList (infList, v.bool);
  997. END Infofiles.
  998.